library(DESeq2)
library(pheatmap)
library(dplyr)
library(dendextend)
library(ggplot2)
#Daniela File path
design_matrix<-read.table('/Users/danielaquijano/Documents/GitHub/Transcriptomics-Final-Project-/source_files/Experimental_Design_TG (1).csv',sep=',',header=TRUE)
head(design_matrix)
#Tasnim File path
#design_matrix<-read.table('/Users/tasnimtabassum/Documents/Transcriptomics_SP22/Experimental_Design_TG.csv',sep=',',header=TRUE)

#head(design_matrix)
rownames(design_matrix)<-design_matrix$Sample
design_matrix$Sample<-NULL

design_matrix
counts_matrix<-read.table("/Users/danielaquijano/Documents/GitHub/Transcriptomics-Final-Project-/Count_Tables/allcounts.csv",sep=',',header=TRUE)
counts_matrix

Because the numbers after the dot in the ensembl IDs represent versions of genes in certain annotations, we can remove these to more easily conduct our differential gene expression analysis.

counts_matrix$V1<-gsub("\\..*","",counts_matrix$V1)

counts_matrix
# remove the "V1" from col 1
rownames(counts_matrix)<-counts_matrix$V1
counts_matrix$V1<-NULL

#head(counts_matrix)

counts_matrix<-counts_matrix[,order(colnames(counts_matrix))]
counts_matrix
design_matrix<-design_matrix[order(rownames(design_matrix)),]

design_matrix
NA

design_matrix$Age = factor(design_matrix$Age)

design_matrix$Age
 [1] eight  eight  two    two    eight  eight  two    two    two    eight  eight  eight 
[13] two    two    eight  eight  two    two    two    two    eight  eight  eight  eight 
[25] two    two    six    six    six    six    twelve twelve twelve twelve twelve twelve
[37] twelve twelve six    six    twelve twelve six    six    twelve twelve six    six   
[49] six    six    twelve twelve six    six    twelve twelve six    six    twelve twelve
[61] twelve twelve twelve twelve six    six    six    six    two    two    eight  eight 
Levels: eight six twelve two
dds <- DESeqDataSetFromMatrix(countData = counts_matrix,
                              colData = design_matrix,
                              design = ~ Age+Genotype)
Warning in DESeqDataSet(se, design = design, ignoreRank) :
  some variables in design formula are characters, converting to factors
dds
class: DESeqDataSet 
dim: 46075 72 
metadata(1): version
assays(1): counts
rownames(46075): ENSMUSG00000000001 ENSMUSG00000000003 ... N_noFeature N_unmapped
rowData names(0):
colnames(72): SRR8512301 SRR8512302 ... SRR8512439 SRR8512440
colData names(3): Model Genotype Age
keep <- rowSums(counts(dds)) >= 10
dds <- dds[keep,]
dds <- DESeq(dds)
estimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 13457 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
normalizedcounts.matrix <- counts(dds,normalized=T)
vst_dds <- vst(dds)

dists <- dist(t(assay(vst_dds)))
head(vst_dds)
class: DESeqTransform 
dim: 6 72 
metadata(1): version
assays(1): ''
rownames(6): ENSMUSG00000000001 ENSMUSG00000000028 ... ENSMUSG00000000049
  ENSMUSG00000000056
rowData names(43): baseMean baseVar ... replace dispFit
colnames(72): SRR8512301 SRR8512302 ... SRR8512439 SRR8512440
colData names(5): Model Genotype Age sizeFactor replaceable


PCA_Genotype<-plotPCA(vst_dds,intgroup=c("Age"))+labs(title = "PCA of mice of different ages", color = "Group")+coord_fixed(ratio=3)
Coordinate system already present. Adding new coordinate system, which will replace the existing one.
PCA_Genotype

resultsNames(dds)
[1] "Intercept"               "Age_six_vs_eight"        "Age_twelve_vs_eight"    
[4] "Age_two_vs_eight"        "Genotype_rtg4510_vs_J20" "Genotype_WT_vs_J20"     
[7] "Genotype_WT_TG_vs_J20"  
dds$Age
 [1] eight  eight  two    two    eight  eight  two    two    two    eight  eight  eight 
[13] two    two    eight  eight  two    two    two    two    eight  eight  eight  eight 
[25] two    two    six    six    six    six    twelve twelve twelve twelve twelve twelve
[37] twelve twelve six    six    twelve twelve six    six    twelve twelve six    six   
[49] six    six    twelve twelve six    six    twelve twelve six    six    twelve twelve
[61] twelve twelve twelve twelve six    six    six    six    two    two    eight  eight 
Levels: eight six twelve two
#Compare 2 vs 8
res_1 <- results(dds, contrast = c("Age", "six", "twelve"))
res1_ordered <- res_1[order(res_1$padj),] 
head(res1_ordered)
log2 fold change (MLE): Age six vs twelve 
Wald test p-value: Age six vs twelve 
DataFrame with 6 rows and 6 columns
                    baseMean log2FoldChange     lfcSE      stat      pvalue        padj
                   <numeric>      <numeric> <numeric> <numeric>   <numeric>   <numeric>
ENSMUSG00000095041 1831.0773      -0.917683 0.1154126  -7.95132 1.84528e-15 2.80538e-11
ENSMUSG00000021280   23.9611      -0.859667 0.1199499  -7.16688 7.67235e-13 5.83214e-09
ENSMUSG00000051242  191.0017      -0.421978 0.0618144  -6.82654 8.69846e-12 4.40809e-08
ENSMUSG00000020914   11.8771       1.650347 0.2570395   6.42060 1.35740e-10 5.15915e-07
ENSMUSG00000009376  146.5615       0.625863 0.1145294   5.46465 4.63819e-08 1.31636e-04
ENSMUSG00000027456   19.2858      -1.120057 0.2062910  -5.42950 5.65116e-08 1.31636e-04

Install Mouse annotation library:

library(biomaRt) #For conversion of transcript IDs to gene ID
library(annotables) #to retrieve grcm38 annotation for mouse genome
library(org.Mm.eg.db) #Mouse genome annotation
library(DOSE)
library(pathview)
library(clusterProfiler)
library(AnnotationHub) 
library(ensembldb)
library(tidyverse)
library(ggnewscale)
# mouse genome load
grcm38

# check that ensgene in our df is prsent in the mouse genome df

idx <- grcm38$ensgene %in% rownames(res1_ordered)
# head(idx)

# df with all the ids that are in our df from the mouse genome df
ids <- grcm38[idx, ]

# head(ids)

# remove duplicates

non_duplicates <- which(duplicated(ids$ensgene) == FALSE)
ids <- ids[non_duplicates, ]

#nrow(res1_ordered)

#rownames(res1_ordered)

# entrezID contains only the IDs that are also in our df

ensgeneID= grcm38[grcm38$ensgene %in% rownames(res1_ordered), ]

# entrezID contains only the IDs that are also in our df

entrezID= grcm38[grcm38$ensgene %in% rownames(res1_ordered), ]
# check nrow ensgeneID
head(ensgeneID)

# create a vector of only the ensgeneIDs
ensgene_ID_vector = c(ensgeneID[[1]])

head(ensgene_ID_vector)
[1] "ENSMUSG00000000001" "ENSMUSG00000000028" "ENSMUSG00000000031" "ENSMUSG00000000037"
[5] "ENSMUSG00000000049" "ENSMUSG00000000056"
# create a vector of only the entrezIDs
entrez_ID_vector = c(entrezID[[2]])

# create a vector of only the gene symbols
gene_symbols = subset(grcm38$symbol, grcm38$ensgene %in% rownames(res1_ordered))

# create new df that contains only the ensgeneIDs, lfc and padj
res2= data.frame(log2foldchange= subset(res1_ordered$log2FoldChange, grcm38$ensgene %in% rownames(res1_ordered)))
padj = subset(res1_ordered$padj, grcm38$ensgene %in% rownames(res1_ordered))
res2 = cbind(padj, res2)
res2 = cbind(ensgene_ID_vector, res2)
res2 = cbind(entrez_ID_vector, res2)
res2 = cbind(gene_symbols, res2)


# omit all "na" values
res2 = na.omit(res2)

res2 <- res2[order(res2$padj),] 
head(res2)
## Significant genes is a vector of fold changes where the names are ENTREZ gene IDs. The background set is a vector of all the genes represented on the platform.

# bg entrez contains all the ensgene

allOEgenes = as.character(res2$ensgene_ID_vector)

# sig res entrez contains all the entrezIDs that have padj <0.05
head(res2)

sigOE <- subset(res2, padj< 0.05)

head(sigOE)
# vector of only lfc values
sigOE_genes = as.character(sigOE$ensgene_ID_vector)

head(sigOE_genes)
[1] "ENSMUSG00000000001" "ENSMUSG00000000028" "ENSMUSG00000000037" "ENSMUSG00000000049"
[5] "ENSMUSG00000000056" "ENSMUSG00000000058"
## Run GO enrichment analysis 
ego <- enrichGO(gene = sigOE_genes, 
                universe = allOEgenes,
                keyType = "ENSEMBL",
                OrgDb = org.Mm.eg.db, 
                ont = "ALL", 
                pAdjustMethod = "BH", 
                qvalueCutoff = 0.05, 
                readable = TRUE,
                pool  = TRUE)

                
## Output results from GO analysis to a table
cluster_summary <- data.frame(ego)

#gene_ratio = cluster_summary[order(cluster_summary$pvalue, decreasing = FALSE), ]
#head(gene_ratio)
ego
#
# over-representation test
#
#...@organism    Mus musculus 
#...@ontology    GOALL 
#...@keytype     ENSEMBL 
#...@gene    chr [1:137] "ENSMUSG00000000001" "ENSMUSG00000000028" "ENSMUSG00000000037" ...
#...pvalues adjusted by 'BH' with cutoff <0.05 
#...48 enriched terms found
'data.frame':   48 obs. of  10 variables:
 $ ONTOLOGY   : chr  "CC" "BP" "BP" "BP" ...
 $ ID         : chr  "GO:0098552" "GO:0050680" "GO:0001937" "GO:0040013" ...
 $ Description: chr  "side of membrane" "negative regulation of epithelial cell proliferation" "negative regulation of endothelial cell proliferation" "negative regulation of locomotion" ...
 $ GeneRatio  : chr  "19/137" "10/137" "6/137" "13/137" ...
 $ BgRatio    : chr  "472/13470" "124/13470" "40/13470" "280/13470" ...
 $ pvalue     : num  2.97e-07 5.19e-07 2.86e-06 5.49e-06 7.12e-06 ...
 $ p.adjust   : num  0.00094 0.00094 0.00346 0.00498 0.00516 ...
 $ qvalue     : num  0.000819 0.000819 0.003014 0.004334 0.004492 ...
 $ geneID     : chr  "Gnai3/Cav2/Ngfr/Fer/Gna12/Th/Scnn1g/Glra1/Itgb2/Cdh1/Lck/Itga5/Gm2a/Btn1a1/Icosl/Il12rb1/Car4/Fasl/Il4" "Apoh/Cav2/Ngfr/Cdh1/Pparg/Acvrl1/Wdr77/Sox9/Krit1/Serpinf1" "Apoh/Cav2/Ngfr/Pparg/Acvrl1/Krit1" "Apoh/Ngfr/Wnt3/Gna12/Cdh1/Pparg/Pdgfb/Acvrl1/Adora3/Krit1/Sema4f/Serpinf1/Il4" ...
 $ Count      : int  19 10 6 13 15 6 11 11 11 11 ...
#...Citation
 T Wu, E Hu, S Xu, M Chen, P Guo, Z Dai, T Feng, L Zhou, W Tang, L Zhan, X Fu, S Liu, X Bo, and G Yu.
 clusterProfiler 4.0: A universal enrichment tool for interpreting omics data.
 The Innovation. 2021, 2(3):100141 
## Dotplot 
dotplot(ego, showCategory=35)+theme(text = element_text(size = 1)) +scale_y_discrete(labels=function(x) str_wrap(x, width=40))+ggtitle('Enriched genes when comparing J20 mice at 6 and 12 months')+ theme(plot.title = element_text(size=16))
Scale for 'y' is already present. Adding another scale for 'y', which will replace the
existing scale.

#barplot(ego, showCategory = 20)
options(ggrepel.max.overlaps = Inf)

## To color genes by log2 fold changes, we need to extract the log2 fold changes from our results table creating a named vector
OE_foldchanges <- sigOE$log2foldchange

names(OE_foldchanges) <- sigOE$gene_symbols

## Cnetplot details the genes associated with one or more terms - by default gives the top 1 significant term (by padj)

cnetplot(ego, 
         categorySize="pvalue", 
         showCategory = 5,
         colorEdge = TRUE,
         circular = FALSE,
         node_label = "all",
         cex_category = 1.5,
         cex_gene = 0.75,
         cex_label_category = 1.5,
         cex_label_gene = 0.75,
         shadowtext = "all")+ggtitle('Enriched genes when comparing rtg4510 mice at 2 and 8 months')

NA
NA
NA
NA
library(enrichplot)
ego2 = pairwise_termsim(ego)
emapplot(ego2, showCategory = 20, colorEdge = TRUE)+ggtitle('Enriched Genes when comparing  mice at 6 and 12 months of age')


# Set-up

#BiocManager::install("SPIA")
library(SPIA)

## Significant genes is a vector of fold changes where the names are ENTREZ gene IDs. The background set is a vector of all the genes represented on the platform.

# bg entrez contains all the entrezIDs 

background_entrez <- res2$entrez_ID_vector

# sig res entrez contains all the entrezIDs that have padj <0.05

sig_res_entrez <- res2[which(res2$padj < 0.05), ]

# vector of only lfc values
sig_entrez <- sig_res_entrez$log2foldchange

head(sig_entrez)


# adding entrezIDs as names for the sig entrez
names(sig_entrez) <- sig_res_entrez$entrez_ID_vector

head(sig_entrez)

# remove dups
dups<-unique(names(sig_entrez[which(duplicated(names(sig_entrez)))]))
sig_entrez<-sig_entrez[!(names(sig_entrez) %in% dups)]


#de= as.vector(sig_entrez)

#de = sort(de, decreasing = FALSE)

# this step takes time

spia_result <- spia(de=sig_entrez, all=background_entrez, organism="mmu", plots=FALSE)
write.csv(spia_result, file = "spia_result_J20_age.csv")

# view one record at a time

subset(spia_result, ID == "04727")

head(res1_ordered)
log2 fold change (MLE): Age six vs twelve 
Wald test p-value: Age six vs twelve 
DataFrame with 6 rows and 6 columns
                    baseMean log2FoldChange     lfcSE      stat      pvalue        padj
                   <numeric>      <numeric> <numeric> <numeric>   <numeric>   <numeric>
ENSMUSG00000095041 1831.0773      -0.917683 0.1154126  -7.95132 1.84528e-15 2.80538e-11
ENSMUSG00000021280   23.9611      -0.859667 0.1199499  -7.16688 7.67235e-13 5.83214e-09
ENSMUSG00000051242  191.0017      -0.421978 0.0618144  -6.82654 8.69846e-12 4.40809e-08
ENSMUSG00000020914   11.8771       1.650347 0.2570395   6.42060 1.35740e-10 5.15915e-07
ENSMUSG00000009376  146.5615       0.625863 0.1145294   5.46465 4.63819e-08 1.31636e-04
ENSMUSG00000027456   19.2858      -1.120057 0.2062910  -5.42950 5.65116e-08 1.31636e-04
norm_counts_top_40 = normalizedcounts.matrix[row.names(head(res1_ordered, 40)), ]
nrow(norm_counts_top_40)
head(design_matrix)

annotation_columns<-design_matrix

row.names(annotation_columns) <- colnames(norm_counts_top_40)

library(pheatmap)

tiff("Heatmap_6,12_age.tiff", width = 7, height = 5, units = 'in', res = 300)
pheatmap(norm_counts_top_40, color=colorRampPalette(c("white", "lightpink", "purple4"))(30), scale="row", cluster_cols = T, show_rownames = T,fontsize = 7,fontsize_row = 4, fontsize_col = 4,labels_row = rownames(dists),annotation_col =annotation_columns,main='Differentially Expressed Genes in rtg4510 mice at 2 and 8 months old' )
dev.off()
null device 
          1 
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CgpsaWJyYXJ5KERFU2VxMikKbGlicmFyeShwaGVhdG1hcCkKbGlicmFyeShkcGx5cikKbGlicmFyeShkZW5kZXh0ZW5kKQpsaWJyYXJ5KGdncGxvdDIpCmBgYAoKYGBge3J9CiNEYW5pZWxhIEZpbGUgcGF0aApkZXNpZ25fbWF0cml4PC1yZWFkLnRhYmxlKCcvVXNlcnMvZGFuaWVsYXF1aWphbm8vRG9jdW1lbnRzL0dpdEh1Yi9UcmFuc2NyaXB0b21pY3MtRmluYWwtUHJvamVjdC0vc291cmNlX2ZpbGVzL0V4cGVyaW1lbnRhbF9EZXNpZ25fVEcgKDEpLmNzdicsc2VwPScsJyxoZWFkZXI9VFJVRSkKaGVhZChkZXNpZ25fbWF0cml4KQpgYGAKCmBgYHtyfQojVGFzbmltIEZpbGUgcGF0aAojZGVzaWduX21hdHJpeDwtcmVhZC50YWJsZSgnL1VzZXJzL3Rhc25pbXRhYmFzc3VtL0RvY3VtZW50cy9UcmFuc2NyaXB0b21pY3NfU1AyMi9FeHBlcmltZW50YWxfRGVzaWduX1RHLmNzdicsc2VwPScsJyxoZWFkZXI9VFJVRSkKCiNoZWFkKGRlc2lnbl9tYXRyaXgpCmBgYAoKYGBge3J9CnJvd25hbWVzKGRlc2lnbl9tYXRyaXgpPC1kZXNpZ25fbWF0cml4JFNhbXBsZQpkZXNpZ25fbWF0cml4JFNhbXBsZTwtTlVMTAoKZGVzaWduX21hdHJpeApgYGAKCmBgYHtyfQpjb3VudHNfbWF0cml4PC1yZWFkLnRhYmxlKCIvVXNlcnMvZGFuaWVsYXF1aWphbm8vRG9jdW1lbnRzL0dpdEh1Yi9UcmFuc2NyaXB0b21pY3MtRmluYWwtUHJvamVjdC0vQ291bnRfVGFibGVzL2FsbGNvdW50cy5jc3YiLHNlcD0nLCcsaGVhZGVyPVRSVUUpCmNvdW50c19tYXRyaXgKYGBgCgoKCkJlY2F1c2UgdGhlIG51bWJlcnMgYWZ0ZXIgdGhlIGRvdCBpbiB0aGUgZW5zZW1ibCBJRHMgcmVwcmVzZW50IHZlcnNpb25zIG9mIGdlbmVzIGluIGNlcnRhaW4gYW5ub3RhdGlvbnMsIHdlIGNhbiByZW1vdmUgdGhlc2UgdG8gbW9yZSBlYXNpbHkgY29uZHVjdCBvdXIgZGlmZmVyZW50aWFsIGdlbmUgZXhwcmVzc2lvbiBhbmFseXNpcy4gCmBgYHtyfQpjb3VudHNfbWF0cml4JFYxPC1nc3ViKCJcXC4uKiIsIiIsY291bnRzX21hdHJpeCRWMSkKCmNvdW50c19tYXRyaXgKYGBgCgpgYGB7cn0KIyByZW1vdmUgdGhlICJWMSIgZnJvbSBjb2wgMQpyb3duYW1lcyhjb3VudHNfbWF0cml4KTwtY291bnRzX21hdHJpeCRWMQpjb3VudHNfbWF0cml4JFYxPC1OVUxMCgojaGVhZChjb3VudHNfbWF0cml4KQoKY291bnRzX21hdHJpeDwtY291bnRzX21hdHJpeFssb3JkZXIoY29sbmFtZXMoY291bnRzX21hdHJpeCkpXQpjb3VudHNfbWF0cml4CmBgYAoKYGBge3J9CmRlc2lnbl9tYXRyaXg8LWRlc2lnbl9tYXRyaXhbb3JkZXIocm93bmFtZXMoZGVzaWduX21hdHJpeCkpLF0KCmRlc2lnbl9tYXRyaXgKCmBgYAoKYGBge3J9CgpkZXNpZ25fbWF0cml4JEFnZSA9IGZhY3RvcihkZXNpZ25fbWF0cml4JEFnZSkKCmRlc2lnbl9tYXRyaXgkQWdlCgoKZGRzIDwtIERFU2VxRGF0YVNldEZyb21NYXRyaXgoY291bnREYXRhID0gY291bnRzX21hdHJpeCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YSA9IGRlc2lnbl9tYXRyaXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2lnbiA9IH4gQWdlK0dlbm90eXBlKQpkZHMKCmtlZXAgPC0gcm93U3Vtcyhjb3VudHMoZGRzKSkgPj0gMTAKZGRzIDwtIGRkc1trZWVwLF0KYGBgCgoKYGBge3J9CmRkcyA8LSBERVNlcShkZHMpCmBgYAoKYGBge3J9Cm5vcm1hbGl6ZWRjb3VudHMubWF0cml4IDwtIGNvdW50cyhkZHMsbm9ybWFsaXplZD1UKQoKYGBgCgoKYGBge3J9CnZzdF9kZHMgPC0gdnN0KGRkcykKCmRpc3RzIDwtIGRpc3QodChhc3NheSh2c3RfZGRzKSkpCmhlYWQodnN0X2RkcykKYGBgCgoKYGBge3J9CgoKUENBX0dlbm90eXBlPC1wbG90UENBKHZzdF9kZHMsaW50Z3JvdXA9YygiQWdlIikpK2xhYnModGl0bGUgPSAiUENBIG9mIG1pY2Ugb2YgZGlmZmVyZW50IGFnZXMiLCBjb2xvciA9ICJHcm91cCIpK2Nvb3JkX2ZpeGVkKHJhdGlvPTMpCgpQQ0FfR2Vub3R5cGUKYGBgCgpgYGB7cn0KcmVzdWx0c05hbWVzKGRkcykKYGBgCmBgYHtyfQpkZHMkQWdlCmBgYAoKYGBge3J9CiNDb21wYXJlIDIgdnMgOApyZXNfMSA8LSByZXN1bHRzKGRkcywgY29udHJhc3QgPSBjKCJBZ2UiLCAic2l4IiwgInR3ZWx2ZSIpKQpyZXMxX29yZGVyZWQgPC0gcmVzXzFbb3JkZXIocmVzXzEkcGFkaiksXSAKaGVhZChyZXMxX29yZGVyZWQpCmBgYAoKCkluc3RhbGwgTW91c2UgYW5ub3RhdGlvbiBsaWJyYXJ5OgoKYGBge3J9CmxpYnJhcnkoYmlvbWFSdCkgI0ZvciBjb252ZXJzaW9uIG9mIHRyYW5zY3JpcHQgSURzIHRvIGdlbmUgSUQKbGlicmFyeShhbm5vdGFibGVzKSAjdG8gcmV0cmlldmUgZ3JjbTM4IGFubm90YXRpb24gZm9yIG1vdXNlIGdlbm9tZQpsaWJyYXJ5KG9yZy5NbS5lZy5kYikgI01vdXNlIGdlbm9tZSBhbm5vdGF0aW9uCmxpYnJhcnkoRE9TRSkKbGlicmFyeShwYXRodmlldykKbGlicmFyeShjbHVzdGVyUHJvZmlsZXIpCmxpYnJhcnkoQW5ub3RhdGlvbkh1YikgCmxpYnJhcnkoZW5zZW1ibGRiKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ25ld3NjYWxlKQpgYGAKCmBgYHtyfQojIG1vdXNlIGdlbm9tZSBsb2FkCmdyY20zOAoKIyBjaGVjayB0aGF0IGVuc2dlbmUgaW4gb3VyIGRmIGlzIHByc2VudCBpbiB0aGUgbW91c2UgZ2Vub21lIGRmCgppZHggPC0gZ3JjbTM4JGVuc2dlbmUgJWluJSByb3duYW1lcyhyZXMxX29yZGVyZWQpCiMgaGVhZChpZHgpCgojIGRmIHdpdGggYWxsIHRoZSBpZHMgdGhhdCBhcmUgaW4gb3VyIGRmIGZyb20gdGhlIG1vdXNlIGdlbm9tZSBkZgppZHMgPC0gZ3JjbTM4W2lkeCwgXQoKIyBoZWFkKGlkcykKCiMgcmVtb3ZlIGR1cGxpY2F0ZXMKCm5vbl9kdXBsaWNhdGVzIDwtIHdoaWNoKGR1cGxpY2F0ZWQoaWRzJGVuc2dlbmUpID09IEZBTFNFKQppZHMgPC0gaWRzW25vbl9kdXBsaWNhdGVzLCBdCmBgYAoKYGBge3J9CgojbnJvdyhyZXMxX29yZGVyZWQpCgojcm93bmFtZXMocmVzMV9vcmRlcmVkKQoKIyBlbnRyZXpJRCBjb250YWlucyBvbmx5IHRoZSBJRHMgdGhhdCBhcmUgYWxzbyBpbiBvdXIgZGYKCmVuc2dlbmVJRD0gZ3JjbTM4W2dyY20zOCRlbnNnZW5lICVpbiUgcm93bmFtZXMocmVzMV9vcmRlcmVkKSwgXQoKIyBlbnRyZXpJRCBjb250YWlucyBvbmx5IHRoZSBJRHMgdGhhdCBhcmUgYWxzbyBpbiBvdXIgZGYKCmVudHJleklEPSBncmNtMzhbZ3JjbTM4JGVuc2dlbmUgJWluJSByb3duYW1lcyhyZXMxX29yZGVyZWQpLCBdCiMgY2hlY2sgbnJvdyBlbnNnZW5lSUQKaGVhZChlbnNnZW5lSUQpCgojIGNyZWF0ZSBhIHZlY3RvciBvZiBvbmx5IHRoZSBlbnNnZW5lSURzCmVuc2dlbmVfSURfdmVjdG9yID0gYyhlbnNnZW5lSURbWzFdXSkKCmhlYWQoZW5zZ2VuZV9JRF92ZWN0b3IpCgoKIyBjcmVhdGUgYSB2ZWN0b3Igb2Ygb25seSB0aGUgZW50cmV6SURzCmVudHJlel9JRF92ZWN0b3IgPSBjKGVudHJleklEW1syXV0pCgojIGNyZWF0ZSBhIHZlY3RvciBvZiBvbmx5IHRoZSBnZW5lIHN5bWJvbHMKZ2VuZV9zeW1ib2xzID0gc3Vic2V0KGdyY20zOCRzeW1ib2wsIGdyY20zOCRlbnNnZW5lICVpbiUgcm93bmFtZXMocmVzMV9vcmRlcmVkKSkKCiMgY3JlYXRlIG5ldyBkZiB0aGF0IGNvbnRhaW5zIG9ubHkgdGhlIGVuc2dlbmVJRHMsIGxmYyBhbmQgcGFkagpyZXMyPSBkYXRhLmZyYW1lKGxvZzJmb2xkY2hhbmdlPSBzdWJzZXQocmVzMV9vcmRlcmVkJGxvZzJGb2xkQ2hhbmdlLCBncmNtMzgkZW5zZ2VuZSAlaW4lIHJvd25hbWVzKHJlczFfb3JkZXJlZCkpKQpwYWRqID0gc3Vic2V0KHJlczFfb3JkZXJlZCRwYWRqLCBncmNtMzgkZW5zZ2VuZSAlaW4lIHJvd25hbWVzKHJlczFfb3JkZXJlZCkpCnJlczIgPSBjYmluZChwYWRqLCByZXMyKQpyZXMyID0gY2JpbmQoZW5zZ2VuZV9JRF92ZWN0b3IsIHJlczIpCnJlczIgPSBjYmluZChlbnRyZXpfSURfdmVjdG9yLCByZXMyKQpyZXMyID0gY2JpbmQoZ2VuZV9zeW1ib2xzLCByZXMyKQoKCiMgb21pdCBhbGwgIm5hIiB2YWx1ZXMKcmVzMiA9IG5hLm9taXQocmVzMikKCnJlczIgPC0gcmVzMltvcmRlcihyZXMyJHBhZGopLF0gCmhlYWQocmVzMikKYGBgCgpgYGB7cn0KIyMgU2lnbmlmaWNhbnQgZ2VuZXMgaXMgYSB2ZWN0b3Igb2YgZm9sZCBjaGFuZ2VzIHdoZXJlIHRoZSBuYW1lcyBhcmUgRU5UUkVaIGdlbmUgSURzLiBUaGUgYmFja2dyb3VuZCBzZXQgaXMgYSB2ZWN0b3Igb2YgYWxsIHRoZSBnZW5lcyByZXByZXNlbnRlZCBvbiB0aGUgcGxhdGZvcm0uCgojIGJnIGVudHJleiBjb250YWlucyBhbGwgdGhlIGVuc2dlbmUKCmFsbE9FZ2VuZXMgPSBhcy5jaGFyYWN0ZXIocmVzMiRlbnNnZW5lX0lEX3ZlY3RvcikKCiMgc2lnIHJlcyBlbnRyZXogY29udGFpbnMgYWxsIHRoZSBlbnRyZXpJRHMgdGhhdCBoYXZlIHBhZGogPDAuMDUKaGVhZChyZXMyKQoKc2lnT0UgPC0gc3Vic2V0KHJlczIsIHBhZGo8IDAuMDUpCgpoZWFkKHNpZ09FKQojIHZlY3RvciBvZiBvbmx5IGxmYyB2YWx1ZXMKc2lnT0VfZ2VuZXMgPSBhcy5jaGFyYWN0ZXIoc2lnT0UkZW5zZ2VuZV9JRF92ZWN0b3IpCgpoZWFkKHNpZ09FX2dlbmVzKQoKYGBgCgoKYGBge3J9CiMjIFJ1biBHTyBlbnJpY2htZW50IGFuYWx5c2lzIAplZ28gPC0gZW5yaWNoR08oZ2VuZSA9IHNpZ09FX2dlbmVzLCAKICAgICAgICAgICAgICAgIHVuaXZlcnNlID0gYWxsT0VnZW5lcywKICAgICAgICAgICAgICAgIGtleVR5cGUgPSAiRU5TRU1CTCIsCiAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5NbS5lZy5kYiwgCiAgICAgICAgICAgICAgICBvbnQgPSAiQUxMIiwgCiAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIiwgCiAgICAgICAgICAgICAgICBxdmFsdWVDdXRvZmYgPSAwLjA1LCAKICAgICAgICAgICAgICAgIHJlYWRhYmxlID0gVFJVRSwKICAgICAgICAgICAgICAgIHBvb2wgID0gVFJVRSkKCiAgICAgICAgICAgICAgICAKIyMgT3V0cHV0IHJlc3VsdHMgZnJvbSBHTyBhbmFseXNpcyB0byBhIHRhYmxlCmNsdXN0ZXJfc3VtbWFyeSA8LSBkYXRhLmZyYW1lKGVnbykKCiNnZW5lX3JhdGlvID0gY2x1c3Rlcl9zdW1tYXJ5W29yZGVyKGNsdXN0ZXJfc3VtbWFyeSRwdmFsdWUsIGRlY3JlYXNpbmcgPSBGQUxTRSksIF0KI2hlYWQoZ2VuZV9yYXRpbykKCgpgYGAKYGBge3J9CmVnbwpgYGAKCgpgYGB7ciBmaWcud2lkdGg9MTUsZmlnLmhlaWdodD0yMH0KIyMgRG90cGxvdCAKZG90cGxvdChlZ28sIHNob3dDYXRlZ29yeT0zNSkrdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMSkpICtzY2FsZV95X2Rpc2NyZXRlKGxhYmVscz1mdW5jdGlvbih4KSBzdHJfd3JhcCh4LCB3aWR0aD00MCkpK2dndGl0bGUoJ0VucmljaGVkIGdlbmVzIHdoZW4gY29tcGFyaW5nIEoyMCBtaWNlIGF0IDYgYW5kIDEyIG1vbnRocycpKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTYpKQoKI2JhcnBsb3QoZWdvLCBzaG93Q2F0ZWdvcnkgPSAyMCkKYGBgCgoKCgoKYGBge3IgZmlnLndpZHRoPTIwLGZpZy5oZWlnaHQ9MjB9Cm9wdGlvbnMoZ2dyZXBlbC5tYXgub3ZlcmxhcHMgPSBJbmYpCgojIyBUbyBjb2xvciBnZW5lcyBieSBsb2cyIGZvbGQgY2hhbmdlcywgd2UgbmVlZCB0byBleHRyYWN0IHRoZSBsb2cyIGZvbGQgY2hhbmdlcyBmcm9tIG91ciByZXN1bHRzIHRhYmxlIGNyZWF0aW5nIGEgbmFtZWQgdmVjdG9yCk9FX2ZvbGRjaGFuZ2VzIDwtIHNpZ09FJGxvZzJmb2xkY2hhbmdlCgpuYW1lcyhPRV9mb2xkY2hhbmdlcykgPC0gc2lnT0UkZ2VuZV9zeW1ib2xzCgojIyBDbmV0cGxvdCBkZXRhaWxzIHRoZSBnZW5lcyBhc3NvY2lhdGVkIHdpdGggb25lIG9yIG1vcmUgdGVybXMgLSBieSBkZWZhdWx0IGdpdmVzIHRoZSB0b3AgMSBzaWduaWZpY2FudCB0ZXJtIChieSBwYWRqKQoKY25ldHBsb3QoZWdvLCAKICAgICAgICAgY2F0ZWdvcnlTaXplPSJwdmFsdWUiLCAKICAgICAgICAgc2hvd0NhdGVnb3J5ID0gNSwKICAgICAgICAgY29sb3JFZGdlID0gVFJVRSwKICAgICAgICAgY2lyY3VsYXIgPSBGQUxTRSwKICAgICAgICAgbm9kZV9sYWJlbCA9ICJhbGwiLAogICAgICAgICBjZXhfY2F0ZWdvcnkgPSAxLjUsCiAgICAgICAgIGNleF9nZW5lID0gMC43NSwKICAgICAgICAgY2V4X2xhYmVsX2NhdGVnb3J5ID0gMS41LAogICAgICAgICBjZXhfbGFiZWxfZ2VuZSA9IDAuNzUsCiAgICAgICAgIHNoYWRvd3RleHQgPSAiYWxsIikrZ2d0aXRsZSgnRW5yaWNoZWQgZ2VuZXMgd2hlbiBjb21wYXJpbmcgcnRnNDUxMCBtaWNlIGF0IDIgYW5kIDggbW9udGhzJykKICAgICAgICAgCgoKCmBgYAoKCmBgYHtyIGZpZy53aWR0aD0xNSxmaWcuaGVpZ2h0PTIwfQpsaWJyYXJ5KGVucmljaHBsb3QpCmVnbzIgPSBwYWlyd2lzZV90ZXJtc2ltKGVnbykKZW1hcHBsb3QoZWdvMiwgc2hvd0NhdGVnb3J5ID0gMjAsIGNvbG9yRWRnZSA9IFRSVUUpK2dndGl0bGUoJ0VucmljaGVkIEdlbmVzIHdoZW4gY29tcGFyaW5nICBtaWNlIGF0IDYgYW5kIDEyIG1vbnRocyBvZiBhZ2UnKQoKYGBgCgoKYGBge3J9CgojIFNldC11cAoKI0Jpb2NNYW5hZ2VyOjppbnN0YWxsKCJTUElBIikKbGlicmFyeShTUElBKQoKIyMgU2lnbmlmaWNhbnQgZ2VuZXMgaXMgYSB2ZWN0b3Igb2YgZm9sZCBjaGFuZ2VzIHdoZXJlIHRoZSBuYW1lcyBhcmUgRU5UUkVaIGdlbmUgSURzLiBUaGUgYmFja2dyb3VuZCBzZXQgaXMgYSB2ZWN0b3Igb2YgYWxsIHRoZSBnZW5lcyByZXByZXNlbnRlZCBvbiB0aGUgcGxhdGZvcm0uCgojIGJnIGVudHJleiBjb250YWlucyBhbGwgdGhlIGVudHJleklEcyAKCmJhY2tncm91bmRfZW50cmV6IDwtIHJlczIkZW50cmV6X0lEX3ZlY3RvcgoKIyBzaWcgcmVzIGVudHJleiBjb250YWlucyBhbGwgdGhlIGVudHJleklEcyB0aGF0IGhhdmUgcGFkaiA8MC4wNQoKc2lnX3Jlc19lbnRyZXogPC0gcmVzMlt3aGljaChyZXMyJHBhZGogPCAwLjA1KSwgXQoKIyB2ZWN0b3Igb2Ygb25seSBsZmMgdmFsdWVzCnNpZ19lbnRyZXogPC0gc2lnX3Jlc19lbnRyZXokbG9nMmZvbGRjaGFuZ2UKCmhlYWQoc2lnX2VudHJleikKCgojIGFkZGluZyBlbnRyZXpJRHMgYXMgbmFtZXMgZm9yIHRoZSBzaWcgZW50cmV6Cm5hbWVzKHNpZ19lbnRyZXopIDwtIHNpZ19yZXNfZW50cmV6JGVudHJlel9JRF92ZWN0b3IKCmhlYWQoc2lnX2VudHJleikKCiMgcmVtb3ZlIGR1cHMKZHVwczwtdW5pcXVlKG5hbWVzKHNpZ19lbnRyZXpbd2hpY2goZHVwbGljYXRlZChuYW1lcyhzaWdfZW50cmV6KSkpXSkpCnNpZ19lbnRyZXo8LXNpZ19lbnRyZXpbIShuYW1lcyhzaWdfZW50cmV6KSAlaW4lIGR1cHMpXQoKCmBgYAoKCgpgYGB7cn0KCgojZGU9IGFzLnZlY3RvcihzaWdfZW50cmV6KQoKI2RlID0gc29ydChkZSwgZGVjcmVhc2luZyA9IEZBTFNFKQoKIyB0aGlzIHN0ZXAgdGFrZXMgdGltZQoKc3BpYV9yZXN1bHQgPC0gc3BpYShkZT1zaWdfZW50cmV6LCBhbGw9YmFja2dyb3VuZF9lbnRyZXosIG9yZ2FuaXNtPSJtbXUiLCBwbG90cz1GQUxTRSkKCmBgYAoKYGBge3J9CndyaXRlLmNzdihzcGlhX3Jlc3VsdCwgZmlsZSA9ICJzcGlhX3Jlc3VsdF9KMjBfYWdlLmNzdiIpCgpgYGAKCgoKYGBge3J9CgojIHZpZXcgb25lIHJlY29yZCBhdCBhIHRpbWUKCnN1YnNldChzcGlhX3Jlc3VsdCwgSUQgPT0gIjA0NzI3IikKCmBgYAoKYGBge3J9CgpoZWFkKHJlczFfb3JkZXJlZCkKbm9ybV9jb3VudHNfdG9wXzQwID0gbm9ybWFsaXplZGNvdW50cy5tYXRyaXhbcm93Lm5hbWVzKGhlYWQocmVzMV9vcmRlcmVkLCA0MCkpLCBdCmBgYAoKYGBge3J9Cm5yb3cobm9ybV9jb3VudHNfdG9wXzQwKQpgYGAKCmBgYHtyfQpoZWFkKGRlc2lnbl9tYXRyaXgpCgphbm5vdGF0aW9uX2NvbHVtbnM8LWRlc2lnbl9tYXRyaXgKCnJvdy5uYW1lcyhhbm5vdGF0aW9uX2NvbHVtbnMpIDwtIGNvbG5hbWVzKG5vcm1fY291bnRzX3RvcF80MCkKCmxpYnJhcnkocGhlYXRtYXApCmBgYAoKYGBge3J9Cgp0aWZmKCJIZWF0bWFwXzYsMTJfYWdlLnRpZmYiLCB3aWR0aCA9IDcsIGhlaWdodCA9IDUsIHVuaXRzID0gJ2luJywgcmVzID0gMzAwKQpwaGVhdG1hcChub3JtX2NvdW50c190b3BfNDAsIGNvbG9yPWNvbG9yUmFtcFBhbGV0dGUoYygid2hpdGUiLCAibGlnaHRwaW5rIiwgInB1cnBsZTQiKSkoMzApLCBzY2FsZT0icm93IiwgY2x1c3Rlcl9jb2xzID0gVCwgc2hvd19yb3duYW1lcyA9IFQsZm9udHNpemUgPSA3LGZvbnRzaXplX3JvdyA9IDQsIGZvbnRzaXplX2NvbCA9IDQsbGFiZWxzX3JvdyA9IHJvd25hbWVzKGRpc3RzKSxhbm5vdGF0aW9uX2NvbCA9YW5ub3RhdGlvbl9jb2x1bW5zLG1haW49J0RpZmZlcmVudGlhbGx5IEV4cHJlc3NlZCBHZW5lcyBpbiBydGc0NTEwIG1pY2UgYXQgMiBhbmQgOCBtb250aHMgb2xkJyApCmRldi5vZmYoKQpgYGAK